package com.zhss.eshop.auth.service.Impl;

import com.zhss.eshop.auth.domain.dto.AuthPriorityDTO;
import com.zhss.eshop.auth.domain.model.AuthPriority;
import com.zhss.eshop.auth.mapper.AuthAccountPriorityRelationshipMapper;
import com.zhss.eshop.auth.mapper.AuthPriorityMapper;
import com.zhss.eshop.auth.mapper.AuthRolePriorityRelationshipMapper;
import com.zhss.eshop.auth.service.AuthPriorityService;
import com.zhss.eshop.auth.service.Impl.operation.PriorityCacheManager;
import com.zhss.eshop.auth.service.Impl.operation.PriorityNode;
import com.zhss.eshop.auth.service.Impl.operation.RelatedCheckPriorityOperation;
import com.zhss.eshop.auth.service.Impl.operation.RemovePriorityOperation;
import com.zhss.eshop.common.bean.SpringApplicationContext;
import com.zhss.eshop.common.constant.CollectionSize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class AuthPriorityServiceImpl implements AuthPriorityService {

    @Resource
    private AuthPriorityMapper authPriorityMapper;

    /**
     * 角色和权限关系管理模块的DAO组件
     */
    @Resource
    private AuthRolePriorityRelationshipMapper rolePriorityRelationshipDAO;
    /**
     * 账号和权限关系管理模块的DAO组件
     */
    @Resource
    private AuthAccountPriorityRelationshipMapper accountPriorityRelationshipDAO;

    /**
     * spring容器组件
     */
    @Autowired
    private SpringApplicationContext context;
    /**
     * 权限缓存管理组件
     */
    @Autowired
    private PriorityCacheManager priorityCacheManager;

    @Override
    public Boolean deleteByPrimaryKey(Long id) throws Exception{
        // 根据id查询权限
        PriorityNode priority = authPriorityMapper.selectByPrimaryKey(id)
                .clone(PriorityNode.class);

        RelatedCheckPriorityOperation relatedCheckPriorityOperation=new RelatedCheckPriorityOperation(authPriorityMapper,rolePriorityRelationshipDAO,accountPriorityRelationshipDAO);
        relatedCheckPriorityOperation.visit(priority);
        Boolean relateCheckResult = relatedCheckPriorityOperation.getRelateCheckResult();

        if(relateCheckResult){
            return false;
        }

        RemovePriorityOperation removePriorityOperation=new RemovePriorityOperation(authPriorityMapper);
        removePriorityOperation.visit(priority);


        // 检查这个权限以及其下任何一个子权限，是否被角色或者账号给关联着
//        RelatedCheckPriorityOperation relatedCheckOperation = context.getBean(
//                RelatedCheckPriorityOperation.class);
//        Boolean relateCheckResult = priority.execute(relatedCheckOperation);
//
//        if(relateCheckResult) {
//            return false;
//        }

        // 递归删除当前权限以及其下所有的子权限
//        RemovePriorityOperation removeOperation = context.getBean(
//                RemovePriorityOperation.class);
//        priority.execute(removeOperation);

        return true;

    }

    @Override
    public int insertSelective(AuthPriorityDTO priorityDTO) throws Exception {
        SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        priorityDTO.setGmtCreate(dateFormatter.parse(dateFormatter.format(new Date())));
        priorityDTO.setGmtModified(dateFormatter.parse(dateFormatter.format(new Date())));
        return authPriorityMapper.insertSelective(priorityDTO.clone(AuthPriority.class));
    }

    @Override
    public AuthPriorityDTO selectByPrimaryKey(Long id) throws Exception {
        AuthPriority authPriority = authPriorityMapper.selectByPrimaryKey(id);
        return authPriority.clone(AuthPriorityDTO.class);
    }

    @Override
    public int updateByPrimaryKeySelective(AuthPriorityDTO priorityDTO) throws Exception {
        return authPriorityMapper.updateByPrimaryKeySelective(priorityDTO.clone(AuthPriority.class));
    }

    @Override
    public List<AuthPriorityDTO> listRootPriorities() throws Exception {
        List<AuthPriority> priorityDOs = authPriorityMapper.listRootPriorities();
        if (priorityDOs == null) {
            return null;
        }
        List<AuthPriorityDTO> priorityDTOs = new ArrayList<AuthPriorityDTO>(priorityDOs.size());
        for (AuthPriority priorityDO : priorityDOs) {
            priorityDTOs.add(priorityDO.clone(AuthPriorityDTO.class));
        }
        return priorityDTOs;
    }

    @Override
    public List<AuthPriorityDTO> listChildPriorities(Long parentId) throws Exception {
        List<AuthPriority> priorityDOs = authPriorityMapper.listChildPriorities(parentId);
        if(priorityDOs == null) {
            return null;
        }

        List<AuthPriorityDTO> priorityDTOs = new ArrayList<AuthPriorityDTO>(priorityDOs.size());
        for(AuthPriority priorityDO : priorityDOs) {
            priorityDTOs.add(priorityDO.clone(AuthPriorityDTO.class));
        }

        return priorityDTOs;
    }

    /**
     * 查询账号被授权的权限树
     * @param accountId 账号id
     * @return 权限树
     * @throws Exception
     */
    @Override
    public List<PriorityNode> listAuthorizedByAccountId(
            Long accountId) throws Exception {
        //查之前先从缓存里取
        List<PriorityNode> authorizedTree = priorityCacheManager
                .getAuthorizedPriorityTree(accountId);
        if(authorizedTree != null) {
            return authorizedTree;
        }

        QueryAuthorizedPriorityOperation operation = context.getBean(
                QueryAuthorizedPriorityOperation.class);
        operation.setAccountId(accountId);

        authorizedTree = new ArrayList<PriorityNode>();

        Map<String, Object> parameters = new HashMap<String, Object>(CollectionSize.DEFAULT);
        parameters.put("accountId", accountId);
        parameters.put("parentId", null);

        List<AuthPriority> authorizedRoots = authPriorityMapper.listAuthroziedByAccountId(parameters);

        for(AuthPriority root : authorizedRoots) {
            PriorityNode targetRoot = root.clone(PriorityNode.class);
            //把每个根节点递归填充好子节点树
            targetRoot.accept(operation);
            authorizedTree.add(targetRoot);
        }

        //查好了放进缓存
        priorityCacheManager.cacheAuthorizedPriorityTree(accountId, authorizedTree);

        return authorizedTree;
    }

    /**
     * 判断账号是否存在对指定编号的权限的授权记录
     * @param AccountId 账号id
     * @param code 权限编号
     * @return 是否存在授权记录
     * @throws Exception
     */
    @Override
    public Boolean existAuthorizedByCode(Long accountId,
                                         String code) throws Exception {
        Boolean authorized = priorityCacheManager.getAuthorizedByCode(accountId, code);
        if(authorized != null) {
            return authorized;
        }

        Long count = authPriorityMapper.countAuthorizedByCode(accountId, code);
        authorized = count > 0 ? true : false;
        priorityCacheManager.cacheAuthorizedByCode(accountId, code, authorized);

        return authorized;
    }
    /**
     * 判断账号是否存在对指定url的权限的授权记录
     * @param AccountId 账号id
     * @param url 权限url
     * @return 是否存在授权记录
     * @throws Exception
     */
    @Override
    public Boolean existAuthorizedByUrl(Long accountId,
                                        String url) throws Exception {
        Boolean authorized = priorityCacheManager.getAuthorizedByUrl(accountId, url);
        if(authorized != null) {
            return authorized;
        }

        Long count = authPriorityMapper.countAuthorizedByUrl(accountId, url);
        authorized = count > 0 ? true : false;
        priorityCacheManager.cacheAuthorizedByUrl(accountId, url, authorized);

        return authorized;
    }
}
